import React from 'react';
import propTypes from 'prop-types';

function getDisplayName(component) {
  return component.displayName || component.name || 'component';
}

const slotProviderHoC = (WrappedComponent) => {

  return class extends React.Component {
    static displayName = `SlotProvider(${getDisplayName(WrappedComponent)})`

    static childContextTypes = {
      requestAddOnRenderer: propTypes.func
    }

    getChildContext() {

      const requestAddOnRenderer = (name) => {
        if (!this.addOnRenderers[name]) {
          return undefined
        }
        return () => (
          this.addOnRenderers[name]
        )
      }

      return {
        requestAddOnRenderer
      };
    }

    addOnRenderers = {}

    render() {
      const { children, ...restProps } = this.props;
      if (children) {
        // 以k-v的方式缓存<AddOn />的内容
        const arr = React.Children.toArray(children);
        const nameChecked = [];
        this.addOnRenderers = {};
        arr.forEach(item => {
          const itemType = item.type;
          if (item.type.displayName === 'AddOn') {
            const slotName = item.props.slot || '$$default';
            // 确保内容唯一性
            if (nameChecked.findIndex(item => item === slotName) !== -1) {
              throw new Error(`Slot(${slotName}) has been occupied`);
            }
            this.addOnRenderers[slotName] = item.props.children;
            nameChecked.push(slotName);
          }
        });
      }

      return (<WrappedComponent {...restProps}></WrappedComponent>);
    }
  };

}

export const SlotProvider = slotProviderHoC;
